// 
// $Rev:: 20            $:  Revision of last commit
// $Author:: rvhaverm@g#$:  Author of last commit
// $Date:: 2010-07-25 1#$:  Date of last commit
// 
package agents.agents;

import java.util.ArrayList;

import agents.core.Components;
import agents.interfaces.IAgent;
import agents.interfaces.IAgentEventListener;
import agents.interfaces.IAgentLifeCycleListener;
import agents.interfaces.IMessage;

import com.ibm.aglet.Aglet;
import com.ibm.aglet.Message;


public abstract class BaseAgent extends Aglet implements IAgent
{
    private ArrayList<IAgentLifeCycleListener> _listeners;
    
    /**
     * Handle any incoming Messages.
     * 
     * This method delegates the incoming Message to the MethodDispatcher.
     * 
     * @param msg
     *            the Message that needs to be handled.
     * @return true if everything goes well.
     */
    public boolean handleMessage(Message msg)
    {
	// transform to IMessage
	// use reflection to instantiate the proper IMessage
	// note that msg.getKind() will give you the exact name of the type
	// to instantiate.

	String className = msg.getKind();
	IMessage m;
	try
	{
	    m = (IMessage) Class.forName(className).newInstance();
	    m.setMessage(msg);
	    receive(m);
	   
	    for (IAgentLifeCycleListener listener : _listeners)
	    {
		listener.onMessageReceived(this, m);
	    }
	    
	    return true;
	}
	catch (InstantiationException e)
	{
	    // TODO Auto-generated catch block
	    e.printStackTrace();
	}
	catch (IllegalAccessException e)
	{
	    // TODO Auto-generated catch block
	    e.printStackTrace();
	}
	catch (ClassNotFoundException e)
	{
	    // TODO Auto-generated catch block
	    e.printStackTrace();
	}

	return false;
    }

    @Override
    public abstract void receive(IMessage message);

    public void addAgentEventListener(IAgentEventListener listener)
    {
	if (_listeners == null) 
	{
	    _listeners = new ArrayList<IAgentLifeCycleListener>();
	}
	_listeners.add(listener);
	this.addCloneListener(listener);
	this.addMobilityListener(listener);
	this.addPersistencyListener(listener);
    }
    
    /**
     * What to do when created.
     * 
     * @param init
     *            an initialization Object.
     */
    public void onCreation(Object init)
    {
	super.onCreation(init);
	
	for (IAgentEventListener listener :Components.Instance().getAgentEventListeners() )
	    addAgentEventListener(listener);
	
	// subscribe to the shutdown-message that will be
	// multi-casted by the UI agent if the user decides
	// to quit the host.
	// TODO: check this string (retrieve it from some factory)
	this.subscribeMessage("agents.msgs.ShuttingDownMessage");
	
	for (IAgentLifeCycleListener listener : _listeners)
	{
	    listener.onCreation(this, init);
	}
    }
    
    /**
     * What to do when disposing.
     * 
     */
    public void onDisposing()
    {
	super.onDisposing();
	
	for (IAgentLifeCycleListener listener : _listeners)
	{
	    listener.onDisposing(this);
	}
    }
    
    public String getHost()
    {
	return this.getAgletContext().getHostingURL().toString();
    }

//    /**
//     * What to do when the host is about to shut down.
//     * 
//     * If subclasses of TASAgent want different behavior than just sending a
//     * reply, they have to override this method.
//     * 
//     * @param msg
//     *            a ShuttingDownHostMessage
//     * @see agents.msgs.ShuttingDownMessage
//     */
//    public void shuttingDownHost(IMessage msg)
//    {
//	AgletBridge.sendReply(msg.getMessage(), "ok");
//    }
}
